//! WARL 寄存器，用于报告 hart 所支持的 ISA。
//!
//! 任何实现中，本寄存器必须可读，但是可以只返回 0 。

use core::marker::PhantomData;

use bits::{BitsOps, IntoBits};

use crate::csrr;

pub fn read() -> usize {
    csrr!(misa)
}
pub fn cache() -> Cache {
    read().into()
}
pub struct Cache {
    pub mxl: u8,
    pub extensions: Extensions,
    phantom: PhantomData<usize>,
}
impl From<usize> for Cache {
    fn from(value: usize) -> Self {
        Cache {
            mxl: 16 << value.bits(usize::BITS - 2..).read(),
            extensions: Extensions {
                raw: value.bits(0..=25).read(),
            },
            phantom: PhantomData,
        }
    }
}
impl Into<usize> for Cache {
    fn into(self) -> usize {
        let mxl = match self.mxl {
            32 => 1,
            64 => 2,
            128 => 3,
            _ => panic!("Invalid mxl, which should be 32|64|128"),
        };
        0usize
            .bits(usize::BITS - 2..)
            .write(mxl)
            .bits(0..=25)
            .write(self.extensions.raw)
    }
}
pub struct Extensions {
    raw: usize,
}
impl Extensions {
    pub fn support(&self, ex: Extension) -> bool {
        self.raw.bits(ex as u32).is_set()
    }
    pub fn disable(&mut self, ex: Extension) -> &mut Self {
        self.raw = self.raw.bits(ex as u32).clr();
        self
    }
    pub fn enable(&mut self, ex: Extension) -> &mut Self {
        self.raw = self.raw.bits(ex as u32).set();
        self
    }
}
pub enum Extension {
    /// 原子（Atomic）扩展
    A = 0,
    /// 目前是保留为 Bit-Manipulation 扩展
    B,
    /// Compressed Extension
    C,
    /// Double-precision floating-point extension
    D,
    /// RV32E base ISA
    E,
    /// Single-precision floating-point extension
    F,
    G,
    H,
    /// RV32I/64I/128I base ISA
    I,
    /// Tentatively reserved for Dynamically Translated Languages extension
    J,
    K,
    L,
    /// Integer Multiply/Divide extension
    M,
    /// Tentatively reserved for User-Level Interrupts extension
    N,
    O,
    /// Tentatively reserved for Packed-SIMD extension
    P,
    /// Quad-precision floating-point extension
    Q,
    R,
    /// Supervisor mode implemented
    S,
    T,
    /// User mode implemented
    U,
    /// Tentatively reserved for Vector extension
    V,
    W,
    /// Non-standard extensions present
    X,
    Y,
    Z,
}
